package com.cv.platform.controller.platform.message;

import com.cv.framework.common.pojo.Result;
import com.cv.framework.common.utils.json.JsonUtil;
import com.cv.framework.security.core.utils.SecurityFrameworkUtil;
import com.cv.platform.controller.platform.message.vo.conversation.CvConversationSaveReqVO;
import com.cv.platform.controller.platform.message.vo.record.CvMessageRecentRespVO;
import com.cv.platform.controller.platform.message.vo.record.CvMessageRespVO;
import com.cv.platform.controller.platform.message.vo.sse.SseRespVO;
import com.cv.platform.service.message.CvConversationService;
import com.cv.platform.service.message.CvConversationVisibleService;
import com.cv.platform.service.message.CvMessageService;
import com.cv.platform.service.message.CvMessageUnreadCountService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.cv.framework.common.pojo.Result.success;

/**
 * 视频平台 - 私信控制器
 *
 * @author Charles_XDXD
 */
@Tag(name = "视频平台 - 私信控制器")
@RestController
@RequestMapping("/platform/message")
public class CvMessageController {

    // 存储每个用户编号的 SseEmitter
    private final Map<Long, SseEmitter> userEmitters = new ConcurrentHashMap<>();

    @Resource
    private CvMessageService cvMessageService;

    @Resource
    private CvMessageUnreadCountService cvMessageUnreadCountService;

    @Resource
    private CvConversationService cvConversationService;

    @Resource
    private CvConversationVisibleService cvConversationVisibleService;

    /**
     * SSE 实时推送未读消息个数
     * SSE 不支持 token 请求头的携带，因此这里需要 PermitAll
     */
    @Operation(summary = "实时推送未读消息个数")
    @GetMapping(value = "/sse/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @PermitAll
    public SseEmitter sse(@PathVariable Long userId) {
        // 超时时间设置为无限
        SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
        userEmitters.put(userId, emitter);

        emitter.onCompletion(() -> userEmitters.remove(userId));
        emitter.onTimeout(() -> userEmitters.remove(userId));

        // 连接成功后立即推送未读消息
        try {
            emitter.send(SseEmitter.event().data(JsonUtil.toJsonString(new SseRespVO("unreadCount", cvMessageUnreadCountService.getTotalCount(userId)))));
        } catch (IOException e) {
            userEmitters.remove(userId);
        }

        return emitter;
    }

    @PostMapping("clearUnreadCount")
    @Operation(summary = "清除未读消息个数")
    public Result<Void> clearUnreadCount(Long conversationId) {
        Long userId = SecurityFrameworkUtil.getLoginUserId();
        cvMessageUnreadCountService.clearUnreadCount(conversationId);
        sendEvent(userId, cvMessageUnreadCountService.getTotalCount(userId));
        return success();
    }

    @GetMapping("getRecentMessageList")
    @Operation(summary = "获得最近聊天列表")
    public Result<List<CvMessageRecentRespVO>> getRecentMessageList() {
        return success(cvMessageService.getRecentList());
    }

    @GetMapping("getMessageList")
    @Operation(summary = "获得聊天列表")
    public Result<List<CvMessageRespVO>> getMessageList(Long conversationId) {
        return success(cvMessageService.getMessageList(conversationId));
    }

    @PostMapping("createConversation")
    @Operation(summary = "创建会话")
    public Result<Long> createConversation(@RequestBody CvConversationSaveReqVO reqVO) {
        return success(cvConversationService.saveConversation(reqVO));
    }

    @GetMapping("getConversationId")
    @Operation(summary = "获得会话编号")
    public Result<Long> getConversationId(Long userId, Long targetId) {
        return success(cvConversationService.getConversationId(userId, targetId));
    }

    @GetMapping("getConversationIsVisible")
    @Operation(summary = "判断会话是否被隐藏")
    public Result<Boolean> getConversationIsVisible(Long conversationId) {
        return success(cvConversationVisibleService.isVisible(conversationId));
    }

    @PutMapping("setConversationVisible")
    @Operation(summary = "设置会话是否可见")
    public Result<Void> hideConversation(Long conversationId, boolean visible) {
        cvConversationVisibleService.setVisible(conversationId, visible);
        return success();
    }

    /**
     * 发送事件
     */
    @PermitAll
    public void sendEvent(Long userId, Object obj) {
        SseEmitter emitter = userEmitters.get(userId);
        if (emitter != null) {
            try {
                emitter.send(SseEmitter.event().data(JsonUtil.toJsonString(new SseRespVO("unreadCount", obj))));
            } catch (IOException e) {
                userEmitters.remove(userId);
            }
        }
    }

}
